#include "jinputcontextwidget.h"
#include "inputmethod/jabstractcandidatepanel.h"
#include "jkeyboardwidget.h"
#include "jpanelmanager.h"

#include <QPlainTextEdit>
#include <QTextEdit>
#include <QLineEdit>
#include <QLabel>

#include <QGuiApplication>
#include <QMouseEvent>
#include <QScreen>
#include <QTimer>

namespace QTE
{

static JKeyboardWidget *gKeyboardWidget = nullptr;

static JPanelManager *gPanelManager = nullptr;

static QFrame *gLine = nullptr;

JInputContextWidget::JInputContextWidget()
{
#if (defined(Q_OS_UNIX) || defined(Q_OS_LINUX)) && !defined(__arm__)
	setWindowFlags(Qt::X11BypassWindowManagerHint);
#endif

	setWindowModality(Qt::ApplicationModal);
	setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip | Qt::Tool);

	gLine = new QFrame(this);
	gLine->setFixedHeight(3);
	gLine->setFrameShadow(QFrame::Sunken);
	gLine->setFrameShape(QFrame::HLine);

	gPanelManager = new JPanelManager(this);
	gKeyboardWidget = new JKeyboardWidget(gPanelManager, this);

	qApp->installEventFilter(this);

	connect(gKeyboardWidget, &JKeyboardWidget::input, this, &JInputContextWidget::input);
	connect(gKeyboardWidget, &JKeyboardWidget::autoPredicts, this, &JInputContextWidget::autoPredicts);
	connect(gKeyboardWidget, &JKeyboardWidget::panelChanged, this, &JInputContextWidget::panelChanged);

	connect(gPanelManager, &JPanelManager::languageChanged, this, [this]()
	{
		auto panel = gPanelManager->candidatePanel();
		if( panel and panel->isValid() )
		{
			panel->setParent(this);
			panel->show();
		}
		setFixedHeight(0);
	});
}

void JInputContextWidget::predicts(QObject *focusObject)
{
	auto panel = gPanelManager->candidatePanel();
	if( panel == nullptr or not panel->isValid() )
		return ;
	{
		auto edit = qobject_cast<QLineEdit*>(focusObject);
		if( edit )
		{
			panel->predicts(edit->text());
			return ;
		}
	}{
		auto edit = qobject_cast<QLabel*>(focusObject);
		if( edit )
		{
			panel->predicts(edit->text());
			return ;
		}
	}{
		auto edit = qobject_cast<QPlainTextEdit*>(focusObject);
		if( edit )
		{
			panel->predicts(edit->toPlainText());
			return ;
		}
	}{
		auto edit = qobject_cast<QTextEdit*>(focusObject);
		if( edit )
			panel->predicts(edit->toPlainText());
	}
}

void JInputContextWidget::setNumberKeyboardLock(bool flag)
{
	gKeyboardWidget->setNumberKeyboardLock(flag);
}

static void layoutAdaptation(JInputContextWidget *parent)
{
	auto rect = qApp->primaryScreen()->availableGeometry();

	int width = rect.width();
	int height = rect.height() >> 1;

	if( width < height )
		height = width;

	else if( width > (height * 3) )
		width = height * 3;

	if( width == parent->width() and height == parent->height() )
		return ;

	int y = 1;
	auto panel = gPanelManager->candidatePanel();

	if( panel and panel->isValid() )
	{
		panel->setParent(parent);
		panel->setFixedWidth(parent->width());

		panel->move(0,y);
		panel->show();

		height += panel->height() + 4;
		y += panel->height() + 4;
	}

	gLine->move(0,y);
	gLine->setFixedWidth(parent->width());

	height += gLine->height() + 1;
	y += gLine->height() + 1;

	parent->setFixedSize(width, height);
	parent->move((rect.width() - width) >> 1, rect.height() - height - 1);

	gKeyboardWidget->setFixedWidth(parent->width());
	gKeyboardWidget->move(0,y);
	gKeyboardWidget->show();
}

void JInputContextWidget::showEvent(QShowEvent *event)
{
	QWidget::showEvent(event);
	layoutAdaptation(this);
}

void JInputContextWidget::resizeEvent(QResizeEvent *event)
{
	QWidget::resizeEvent(event);
	layoutAdaptation(this);
}

bool JInputContextWidget::eventFilter(QObject *object, QEvent *event)
{
	if( object != gKeyboardWidget )
		return false;

	else if( event->type() == QEvent::Hide or event->type() == QEvent::Close )
	{
		gKeyboardWidget->show();
		hide();
	}
	return false;
}

} //namespace QTE
